﻿using SdmxMl.Structure;
using Telerik.WinControls.UI;

namespace PluginMeb
{
    /// <summary>
    /// Manages grid table for Ausbildung combinations
    /// </summary>
    public class GridAusbild
    {
        #region Internal Menbers

        public RadGridView gridView { get; private set; }
        private MatrixCache cache;

        #endregion

        #region Constructor

        /// <summary> C'tor </summary>
        /// <param name="grid">Grid control to use</param>
        /// <param name="mx">Metadata cache provider</param>
        public GridAusbild(RadGridView grid, MatrixCache mx)
        {
            gridView = grid;
            cache = mx;

            // Construct columns and create one empty row
            gridView.BeginUpdate();
            gridView.MasterTemplate.Rows.Clear();
            gridView.MasterTemplate.Columns.Clear();

            foreach (CodeType code in cache.CltAusbildForm.CodeList)
            {
                GridViewCheckBoxColumn colCheck = new GridViewCheckBoxColumn(code.Id);
                colCheck.HeaderText = code.Name.ToString();
                colCheck.Width = 90;
                gridView.MasterTemplate.Columns.Add(colCheck);

                // Valid from and to
                GridViewDecimalColumn decimalColumn = new GridViewDecimalColumn("VF_" + code.Id);
                decimalColumn.HeaderText = "from";
                decimalColumn.DecimalPlaces = 0;
                decimalColumn.Maximum = 3000;
                decimalColumn.Width = 47;
                gridView.MasterTemplate.Columns.Add(decimalColumn);


                decimalColumn = new GridViewDecimalColumn("VT_" + code.Id);
                decimalColumn.HeaderText = "to";
                decimalColumn.DecimalPlaces = 0;
                decimalColumn.Maximum = 3000;
                decimalColumn.Width = 47;
                gridView.MasterTemplate.Columns.Add(decimalColumn);

            }

            gridView.EndUpdate();
            // Create row with no check
            GridViewRowInfo row = gridView.MasterTemplate.Rows.NewRow();
            gridView.MasterTemplate.Rows.Add(row);
            ResetRow();

        }

        /// <summary>Initialize content of unique row representing combinations </summary>
        private void ResetRow()
        {
            if ( gridView.MasterTemplate.Rows.Count == 1)
            {
                foreach (GridViewColumn col in gridView.MasterTemplate.Columns)
                {
                    if (col is GridViewDecimalColumn)
                        gridView.MasterTemplate.Rows[0].Cells[col.Name].Value = null;
                    else if (col is GridViewCheckBoxColumn)
                        gridView.MasterTemplate.Rows[0].Cells[col.Name].Value = false;
                }
            }
        }

        #endregion

        #region Update content

        public void UpdateLanguage()
        {
            foreach (CodeType code in cache.CltAusbildForm.CodeList)
                gridView.MasterTemplate.Columns[code.Id].HeaderText = code.Name.ToString();
       }

        /// <summary> Update table content according to selected Schulart</summary>
        /// <param name="schulArtId">the targeted schulart</param>
        public void RefreshKombi(string schulArtId)
        {
            // Reset
            ResetRow();

            // and set existing
            GetKombiForSchulart(schulArtId);
        }

        /// <summary>
        /// Update table row content according to selected Schulart
        /// </summary>
        /// <param name="schulArtId">the targeted schulart</param>
        private void GetKombiForSchulart(string schulArtId)
        {
            CodeRefType cref = LocateKombiSchulart(schulArtId);
            if (cref != null)
            {
                foreach (CodeRefType cr in cref.CodeRefList)
                {
                    gridView.MasterTemplate.Rows[0].Cells[cr.CodeID].Value = true;
                    gridView.MasterTemplate.Rows[0].Cells["VF_" + cr.CodeID].Value = GetYearOfDate(cr.ValidFrom);
                    gridView.MasterTemplate.Rows[0].Cells["VT_" + cr.CodeID].Value = GetYearOfDate(cr.ValidTo);
                }
            }
            else
            {
                ResetRow();
            }

        }
        private CodeRefType LocateKombiSchulart(string schulArtId)
        {
            CodeRefType crefSchulart = null;

            // locates schulart code in top level hierarchy
            HierarchyType hi = cache.HclKombination.HierarchyList[0];
            foreach (CodeRefType cref in hi.CodeRefList)
            {
                // targeted schulart located ?
                if (cref.CodeID == schulArtId)
                {
                    crefSchulart = cref;
                    break;
                }
            }
            return crefSchulart;
        }

        public bool EraseKombi(string schulArtId)
        {
            bool erased = false;

            // Get current container
            CodeRefType crefSchulart = LocateKombiSchulart(schulArtId);
            if (crefSchulart != null)
            {
                cache.HclKombination.HierarchyList[0].CodeRefList.Remove(crefSchulart);
                erased = true;
            }


            return erased;
        }

        public bool SetKombiForSchulart(string schulArtId)
        {
            bool updated = false;

            // Get current container
            CodeRefType crefSchulart = LocateKombiSchulart(schulArtId);

            // Create new one
            CodeRefType crefNew = new CodeRefType(schulArtId, cache.HclKombination.CodelistRefList[0].Alias);

            foreach (CodeType code in cache.CltAusbildForm.CodeList)
            {
                if (System.Convert.ToBoolean(gridView.MasterTemplate.Rows[0].Cells[code.Id].Value) == true)
                {
                    CodeRefType cr = new CodeRefType(code.Id, cache.HclKombination.CodelistRefList[1].Alias);
                    crefNew.CodeRefList.Add(cr);
                    // Has valid from
                    if (gridView.MasterTemplate.Rows[0].Cells["VF_" + code.Id].Value != null)
                        cr.ValidFrom = gridView.MasterTemplate.Rows[0].Cells["VF_" + code.Id].Value.ToString() + ".01.01";

                    // Has valid to
                    if (gridView.MasterTemplate.Rows[0].Cells["VT_" + code.Id].Value != null)
                        cr.ValidTo = gridView.MasterTemplate.Rows[0].Cells["VT_" + code.Id].Value.ToString() + ".01.01";
                }
            }

            // Changes ?
            if ((updated = IsKombiModified(crefSchulart, crefNew)) == true)
            {
                if (crefSchulart == null)
                    cache.HclKombination.HierarchyList[0].CodeRefList.Add(crefNew);
                else
                {
                    // Clear old content
                    crefSchulart.CodeRefList.Clear();
                    foreach (CodeRefType cr in crefNew.CodeRefList)
                        crefSchulart.CodeRefList.Add(cr);
                }
            }
            return updated;
        }

        public bool IsKombiModified(CodeRefType crefSchulartOrg, CodeRefType crefSchulartNew)
        {
            // new ref is never null
            bool modif = crefSchulartOrg == null && crefSchulartNew.CodeRefList.Count > 0 ||
                crefSchulartOrg != null && crefSchulartOrg.CodeRefList.Count != crefSchulartNew.CodeRefList.Count;
            if (!modif)
            {
                foreach (CodeRefType crNew in crefSchulartNew.CodeRefList)
                {
                    bool match = false;
                    foreach (CodeRefType crOld in crefSchulartOrg.CodeRefList)
                    {
                        if (crNew.CodeID == crOld.CodeID &&
                            IsSameDate(crNew.ValidFrom, crOld.ValidFrom) &&
                            IsSameDate(crNew.ValidTo, crOld.ValidTo))
                        {
                            match = true;
                            break;
                        }

                    }
                    if (!match)
                    {
                        modif = true;
                        break;
                    }
               }
            }


            return modif;
        }

        
        /// <summary> Kombi needs only the year part of the validity info </summary>
        /// <param name="date">full validity date string</param>
        /// <returns>Year part of date or empty if not specified</returns>
        private object GetYearOfDate(string date)
        {
            object answer = null;
            if (date != null && date.Length >= 4)
                answer = System.Convert.ToInt32(date.Substring(0, 4));
            return answer;
        }

        private bool IsSameDate(string dateOne, string dateTwo)
        {
            object one = GetYearOfDate(dateOne);
            object two = GetYearOfDate(dateTwo);
            return (one == null && two == null) ||
                (one != null && two != null && one.ToString() == two.ToString());


        }
        #endregion
    }
}
